﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iriska;
using jabber;
using jabber.connection;
using System.Reflection;
using System.IO;

namespace WordsGame
{
    public class GamePlugin : AbstractPlugin
    {
        private string _dictionaryFileName;

        private string _validWordsFileName;

        private Game _game;

        public GamePlugin()
        {
            var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            _dictionaryFileName = Path.Combine(directory, Properties.Settings.Default.Dictionary);
            _validWordsFileName = Path.Combine(directory, Properties.Settings.Default.ValidWords);
            

            IList<string> strings = new List<string>(File.ReadAllLines(_dictionaryFileName));
            IList<string> validWords = new List<string>(File.ReadAllLines(_validWordsFileName));

            Tree tree = new Tree();
            foreach (var word in validWords)
            {
                tree.Add(word);
            }

            var standsFileName = Path.Combine(directory, Properties.Settings.Default.Standings);
            _game = new Game(strings, tree, new StandingsProvider(standsFileName));
        }

        public override void Process(ConfMessage message, jabber.connection.Room room)
        {
            try
            {
                var commandType = ToCommandType(message.Message);
                switch(commandType)
                {
                    case CommandType.Start:
                        _game.Start();
                        room.PublicMessage(string.Format("{0} started the game", message.From));
                        room.PublicMessage(string.Format("word is {0}", _game.CurrentWord));
                        break;

                    case CommandType.Stop:
                        _game.Stop();
                        room.PublicMessage("game stopped");
                        break;

                    case CommandType.Top:
                        var standings = _game.GetStandings();
                        for (int i = 0; i < standings.Players.Count; ++i)
                        {
                            var player = standings.Players[i];
                            room.PublicMessage(string.Format("#{0}: {1,-10}{2,10}", i + 1, player.Name, player.Score));
                        }

                        break;

                    case CommandType.Unknown:
                        var result = _game.MakeMove(message.From, message.Message);
                        if (result > 0)
                        {
                            room.PublicMessage(string.Format("{0} +{1}", message.From, result));
                        }

                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            catch (Exception exception)
            {
                room.PublicMessage(string.Format("{0} broke everything", message.From));
                room.PublicMessage(exception.Message);
#if DEBUG
                room.PublicMessage(exception.StackTrace);
#endif
            }
        }

        public override string PluginName()
        {
            return "WordsGame plugin";
        }

        private CommandType ToCommandType(string command)
        {
            Func<string, string, bool> areEqual = (a, b) =>
                string.Compare(a, b, StringComparison.OrdinalIgnoreCase) == 0;
            var commandToType = new Dictionary<string, CommandType>
                {
                    { "!start", CommandType.Start },
                    { "!stop", CommandType.Stop },
                    { "!top", CommandType.Top },
                };

            foreach (var pair in commandToType.Where(pair => areEqual(pair.Key, command)))
            {
                return pair.Value;
            }

            return CommandType.Unknown;
        }
    }
}
